package message

import (
	"encoding/json"
	"fmt"

	"gitee.com/douxuefeng/go-utils/request"
	"gitee.com/douxuefeng/go-utils/wechat/corp/params"
)

const messageUrl string = params.CorpApi + "/message/send?access_token=%s"

type Policy interface {
	Send(token string) *params.MessageReply
}

type MessageInterface interface {
	MessageText | MessageCard | MessageFile | MessageImage | MessageMarkdown | MessageVoice | MessageMiniProgramNotice | MessageNews | MessageVideo
}

type msg[T MessageInterface] struct {
	Data *T
}

func NewMsg[T MessageInterface](data *T) *msg[T] {
	return &msg[T]{data}
}

func (a *msg[T]) Send(token string) *params.MessageReply {
	req := request.NewRequest()
	req.SetBody(a.Data)
	rsp, err := req.Post(fmt.Sprintf(messageUrl, token))
	if err != nil {
		return &params.MessageReply{Errcode: 1, Errmsg: err.Error()}
	}
	var rs params.MessageReply
	err = json.Unmarshal(rsp.Body(), &rs)
	if err != nil {
		return &params.MessageReply{Errcode: 1, Errmsg: err.Error()}
	}
	return &rs
}

type MessageBase struct {
	// 指定接收消息的成员，成员ID列表（多个接收者用‘|’分隔，最多支持1000个）。特殊情况：指定为"@all"，则向该企业应用的全部成员发送
	Touser string `json:"touser"`
	// 指定接收消息的部门，部门ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为"@all"时忽略本参数
	Toparty string `json:"toparty"`
	// 指定接收消息的标签，标签ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为"@all"时忽略本参数
	Totag string `json:"totag"`
	// 企业应用的id，整型。企业内部开发，可在应用的设置页面查看；第三方服务商，可通过接口 获取企业授权信息 获取该参数值
	Agentid int `json:"agentid"`
	// 表示是否开启id转译，0表示否，1表示是，默认0。仅第三方应用需要用到，企业自建应用可以忽略。
	EnableIdTrans int `json:"enable_id_trans"`
	// 表示是否开启重复消息检查，0表示否，1表示是，默认0
	EnableDuplicateCheck int `json:"enable_duplicate_check"`
	// 表示是否重复消息检查的时间间隔，默认1800s，最大不超过4小时
	DuplicateCheckInterval int `json:"duplicate_check_interval"`
}

// 文本消息
type MessageText struct {
	MessageBase
	// 消息类型，此时固定为：text
	Msgtype string `json:"msgtype"`
	// 消息内容，最长不超过2048个字节，超过将截断（支持id转译）
	Text struct {
		Content string `json:"content"`
	} `json:"text"`
	// 表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
	Safe int `json:"safe"`
}

// 图片消息
type MessageImage struct {
	MessageBase
	// 消息类型，此时固定为：image
	Msgtype string `json:"msgtype"`
	// 图片消息的媒体id，可以调用获取媒体文件接口拉取数据
	Image struct {
		MediaId string `json:"media_id"`
	} `json:"image"`
	//  表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
	Safe int `json:"safe"`
}

// 语音消息
type MessageVoice struct {
	MessageBase
	// 消息类型，此时固定为：voice
	Msgtype string `json:"msgtype"`
	// 语音消息的媒体id，可以调用获取媒体文件接口拉取数据
	Voice struct {
		MediaId string `json:"media_id"`
	} `json:"voice"`
}

// 视频消息
type MessageVideo struct {
	MessageBase
	// 消息类型，此时固定为：video
	Msgtype string `json:"msgtype"`
	// 视频消息的媒体id，可以调用获取媒体文件接口拉取数据
	Video struct {
		MediaId string `json:"media_id"`
	} `json:"video"`
	Title string `json:"title"`
	//  视频消息的描述，不超过500个字节，超过将截断（支持id转译）
	Description string `json:"description"`
	// 表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
	Safe int `json:"safe"`
}

// 文件消息
type MessageFile struct {
	MessageBase
	// 消息类型，此时固定为：file
	Msgtype string `json:"msgtype"`
	// 文件消息的媒体id，可以调用获取媒体文件接口拉取数据
	File struct {
		MediaId string `json:"media_id"`
	} `json:"file"`
	//  表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
	Safe int `json:"safe"`
}

// 文本卡片信息
type MessageCard struct {
	MessageBase
	// 消息类型，此时固定为：textcard
	Msgtype string `json:"msgtype"`
	// 文本卡片消息
	Textcard struct {
		Title string `json:"title"`
		//  文本内容，支持id转译，不超过600个字节，超过将截断（支持id转译）
		Description string `json:"description"`
		// 表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
		Url string `json:"url"`
	} `json:"textcard"`
	// 按钮文字。 默认为“详情”， 不超过4个文字，超过自动截断
	Btntxt string `json:"btntxt"`
	// 表示是否是保密消息，0表示可对外分享，1表示不能分享且内容显示水印，默认为0
	Safe int `json:"safe"`
}

// 图文消息
type MessageNews struct {
	MessageBase
	// 消息类型，此时固定为：news
	Msgtype string `json:"msgtype"`
	// 消息体 len <=8
	Mpnews struct {
		Articles []struct {
			Title            string `json:"title"`
			ThumbMediaId     string `json:"thumb_media_id"`
			Author           string `json:"author"`
			ContentSourceUrl string `json:"content_source_url"`
			Content          string `json:"content"`
			Digest           string `json:"digest"`
		} `json:"articles"`
	} `json:"mpnews"`
	Safe int `json:"safe"`
}

// markdown消息
type MessageMarkdown struct {
	MessageBase
	// 消息类型，此时固定为：markdown
	Msgtype string `json:"msgtype"`
	// markdown消息体
	Markdown struct {
		Content string `json:"content"`
	} `json:"markdown"`
}

// 小程序通知消息
type MessageMiniProgramNotice struct {
	MessageBase
	// 消息类型，此时固定为：miniprogram_notice
	Msgtype string `json:"msgtype"`
	// 小程序通知消息体
	MiniProgramNotice struct {
		// appid
		Appid string `json:"appid"`
		// 页面路径
		Page string `json:"page"`
		// 标题
		Title string `json:"title"`
		// 描述
		Description string `json:"description"`
		// 是否放大第一个content_item
		EmphasisFirstChatItem bool `json:"emphasis_first_chat_item"`
		// 内容列表
		ContentItem []struct {
			Key string `json:"key"`
			// 内容
			Value string `json:"value"`
		} `json:"content_item"`
	}
}
